{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4e6ad1cf-7475-4a70-a9d0-d6b3a96efaa6",
   "metadata": {},
   "outputs": [],
   "source": [
    "房价预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8f82fc49-5060-419c-b9e1-b11aa498806e",
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import sys\n",
    "sys.path.append(\"..\") \n",
    "import d2lzh_pytorch as d2l"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "dbb323dc-4dca-47ae-a02c-3894c629726f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.5.0\n"
     ]
    }
   ],
   "source": [
    "print(torch.__version__)\n",
    "# 设置默认数据类型为 float32 (相当于原来的 FloatTensor)\n",
    "torch.set_default_dtype(torch.float32)\n",
    "\n",
    "# 设置默认设备为 CPU (如果你想使用 GPU，可以将 'cpu' 改为 'cuda')\n",
    "torch.set_default_device('cuda')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "60f2123e-73dd-48cb-aaf6-73c380e15dcd",
   "metadata": {},
   "outputs": [],
   "source": [
    "train_data = pd.read_csv('dataset/train.csv')\n",
    "test_data = pd.read_csv('dataset/test.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "1159503c-bd83-49f5-82c8-a37f2f664845",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1459, 80)"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_data.shape\n",
    "test_data.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "a6a93d8a-db7e-4d15-950f-a48836f819fe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Id</th>\n",
       "      <th>MSSubClass</th>\n",
       "      <th>MSZoning</th>\n",
       "      <th>LotFrontage</th>\n",
       "      <th>SaleType</th>\n",
       "      <th>SaleCondition</th>\n",
       "      <th>SalePrice</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>60</td>\n",
       "      <td>RL</td>\n",
       "      <td>65.0</td>\n",
       "      <td>WD</td>\n",
       "      <td>Normal</td>\n",
       "      <td>208500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>20</td>\n",
       "      <td>RL</td>\n",
       "      <td>80.0</td>\n",
       "      <td>WD</td>\n",
       "      <td>Normal</td>\n",
       "      <td>181500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>60</td>\n",
       "      <td>RL</td>\n",
       "      <td>68.0</td>\n",
       "      <td>WD</td>\n",
       "      <td>Normal</td>\n",
       "      <td>223500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>70</td>\n",
       "      <td>RL</td>\n",
       "      <td>60.0</td>\n",
       "      <td>WD</td>\n",
       "      <td>Abnorml</td>\n",
       "      <td>140000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Id  MSSubClass MSZoning  LotFrontage SaleType SaleCondition  SalePrice\n",
       "0   1          60       RL         65.0       WD        Normal     208500\n",
       "1   2          20       RL         80.0       WD        Normal     181500\n",
       "2   3          60       RL         68.0       WD        Normal     223500\n",
       "3   4          70       RL         60.0       WD       Abnorml     140000"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#观察前四个样本的前四个特征、后两个特征和标签\n",
    "train_data.iloc[0:4, [0, 1, 2, 3, -3, -2, -1]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "17e7f0cf-3103-4dfc-8768-5cf97d39518a",
   "metadata": {},
   "outputs": [],
   "source": [
    "#将训练数据集与测试数据集的特征按照样本连接起来\n",
    "all_features = pd.concat((train_data.iloc[:, 1:-1], test_data.iloc[:, 1:]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "be146283-1728-4f36-9abb-f39407620a9a",
   "metadata": {},
   "outputs": [],
   "source": [
    "#识别出所有数值型特征\n",
    "numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index\n",
    "#数据标准化为均值为0，标准差为1。\n",
    "#print(all_features[numeric_features])\n",
    "all_features[numeric_features] = all_features[numeric_features].apply(lambda x: (x - x.mean()) / (x.std()))\n",
    "# 标准化后，每个特征的均值变为0，所以可以直接⽤0来替换缺失值\n",
    "all_features = all_features.fillna(0)\n",
    "#print(all_features[numeric_features])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "811fa885-8019-4c0b-9b88-341e0430f2af",
   "metadata": {},
   "outputs": [],
   "source": [
    "为什么将离散值转换成指示特征？\n",
    "大多数机器学习算法（尤其是基于线性模型的算法、神经网络等）只能处理数值型数据\n",
    "而离散的类别型数据（如性别、城市、产品种类等）本身不能直接作为输入进行计算。\n",
    "如果不对这些离散特征进行适当转换，模型可能无法正确理解和处理它们。\n",
    "独热编码可以帮助这些模型从多个维度独立地处理每个类别，使用二进制特征避免形成2>1的情况\n",
    "从而避免因为类别值之间的数量差异或顺序关系而造成的误解。\n",
    "通过这种方式，模型可以更好地从数据中学习规律。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "385bad25-8854-4cb7-9f7b-2c2aeda131e2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>MSSubClass</th>\n",
       "      <th>LotFrontage</th>\n",
       "      <th>LotArea</th>\n",
       "      <th>OverallQual</th>\n",
       "      <th>OverallCond</th>\n",
       "      <th>YearBuilt</th>\n",
       "      <th>YearRemodAdd</th>\n",
       "      <th>MasVnrArea</th>\n",
       "      <th>BsmtFinSF1</th>\n",
       "      <th>BsmtFinSF2</th>\n",
       "      <th>...</th>\n",
       "      <th>SaleType_Oth</th>\n",
       "      <th>SaleType_WD</th>\n",
       "      <th>SaleType_nan</th>\n",
       "      <th>SaleCondition_Abnorml</th>\n",
       "      <th>SaleCondition_AdjLand</th>\n",
       "      <th>SaleCondition_Alloca</th>\n",
       "      <th>SaleCondition_Family</th>\n",
       "      <th>SaleCondition_Normal</th>\n",
       "      <th>SaleCondition_Partial</th>\n",
       "      <th>SaleCondition_nan</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.067320</td>\n",
       "      <td>-0.202033</td>\n",
       "      <td>-0.217841</td>\n",
       "      <td>0.646073</td>\n",
       "      <td>-0.507197</td>\n",
       "      <td>1.046078</td>\n",
       "      <td>0.896679</td>\n",
       "      <td>0.525112</td>\n",
       "      <td>0.580807</td>\n",
       "      <td>-0.29308</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-0.873466</td>\n",
       "      <td>0.501785</td>\n",
       "      <td>-0.072032</td>\n",
       "      <td>-0.063174</td>\n",
       "      <td>2.187904</td>\n",
       "      <td>0.154737</td>\n",
       "      <td>-0.395536</td>\n",
       "      <td>-0.572152</td>\n",
       "      <td>1.177910</td>\n",
       "      <td>-0.29308</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.067320</td>\n",
       "      <td>-0.061269</td>\n",
       "      <td>0.137173</td>\n",
       "      <td>0.646073</td>\n",
       "      <td>-0.507197</td>\n",
       "      <td>0.980053</td>\n",
       "      <td>0.848819</td>\n",
       "      <td>0.334770</td>\n",
       "      <td>0.097856</td>\n",
       "      <td>-0.29308</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.302516</td>\n",
       "      <td>-0.436639</td>\n",
       "      <td>-0.078371</td>\n",
       "      <td>0.646073</td>\n",
       "      <td>-0.507197</td>\n",
       "      <td>-1.859033</td>\n",
       "      <td>-0.682695</td>\n",
       "      <td>-0.572152</td>\n",
       "      <td>-0.494856</td>\n",
       "      <td>-0.29308</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.067320</td>\n",
       "      <td>0.689469</td>\n",
       "      <td>0.518814</td>\n",
       "      <td>1.355319</td>\n",
       "      <td>-0.507197</td>\n",
       "      <td>0.947040</td>\n",
       "      <td>0.753100</td>\n",
       "      <td>1.387248</td>\n",
       "      <td>0.468851</td>\n",
       "      <td>-0.29308</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1454</th>\n",
       "      <td>2.419286</td>\n",
       "      <td>-2.266564</td>\n",
       "      <td>-1.043758</td>\n",
       "      <td>-1.481667</td>\n",
       "      <td>1.289537</td>\n",
       "      <td>-0.043338</td>\n",
       "      <td>-0.682695</td>\n",
       "      <td>-0.572152</td>\n",
       "      <td>-0.969026</td>\n",
       "      <td>-0.29308</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1455</th>\n",
       "      <td>2.419286</td>\n",
       "      <td>-2.266564</td>\n",
       "      <td>-1.049083</td>\n",
       "      <td>-1.481667</td>\n",
       "      <td>-0.507197</td>\n",
       "      <td>-0.043338</td>\n",
       "      <td>-0.682695</td>\n",
       "      <td>-0.572152</td>\n",
       "      <td>-0.415828</td>\n",
       "      <td>-0.29308</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1456</th>\n",
       "      <td>-0.873466</td>\n",
       "      <td>4.255477</td>\n",
       "      <td>1.246594</td>\n",
       "      <td>-0.772420</td>\n",
       "      <td>1.289537</td>\n",
       "      <td>-0.373465</td>\n",
       "      <td>0.561660</td>\n",
       "      <td>-0.572152</td>\n",
       "      <td>1.717937</td>\n",
       "      <td>-0.29308</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1457</th>\n",
       "      <td>0.655311</td>\n",
       "      <td>-0.342796</td>\n",
       "      <td>0.034599</td>\n",
       "      <td>-0.772420</td>\n",
       "      <td>-0.507197</td>\n",
       "      <td>0.682939</td>\n",
       "      <td>0.370221</td>\n",
       "      <td>-0.572152</td>\n",
       "      <td>-0.229233</td>\n",
       "      <td>-0.29308</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1458</th>\n",
       "      <td>0.067320</td>\n",
       "      <td>0.220258</td>\n",
       "      <td>-0.068608</td>\n",
       "      <td>0.646073</td>\n",
       "      <td>-0.507197</td>\n",
       "      <td>0.715952</td>\n",
       "      <td>0.465941</td>\n",
       "      <td>-0.045913</td>\n",
       "      <td>0.694959</td>\n",
       "      <td>-0.29308</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>2919 rows × 353 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "      MSSubClass  LotFrontage   LotArea  OverallQual  OverallCond  YearBuilt  \\\n",
       "0       0.067320    -0.202033 -0.217841     0.646073    -0.507197   1.046078   \n",
       "1      -0.873466     0.501785 -0.072032    -0.063174     2.187904   0.154737   \n",
       "2       0.067320    -0.061269  0.137173     0.646073    -0.507197   0.980053   \n",
       "3       0.302516    -0.436639 -0.078371     0.646073    -0.507197  -1.859033   \n",
       "4       0.067320     0.689469  0.518814     1.355319    -0.507197   0.947040   \n",
       "...          ...          ...       ...          ...          ...        ...   \n",
       "1454    2.419286    -2.266564 -1.043758    -1.481667     1.289537  -0.043338   \n",
       "1455    2.419286    -2.266564 -1.049083    -1.481667    -0.507197  -0.043338   \n",
       "1456   -0.873466     4.255477  1.246594    -0.772420     1.289537  -0.373465   \n",
       "1457    0.655311    -0.342796  0.034599    -0.772420    -0.507197   0.682939   \n",
       "1458    0.067320     0.220258 -0.068608     0.646073    -0.507197   0.715952   \n",
       "\n",
       "      YearRemodAdd  MasVnrArea  BsmtFinSF1  BsmtFinSF2  ...  SaleType_Oth  \\\n",
       "0         0.896679    0.525112    0.580807    -0.29308  ...             0   \n",
       "1        -0.395536   -0.572152    1.177910    -0.29308  ...             0   \n",
       "2         0.848819    0.334770    0.097856    -0.29308  ...             0   \n",
       "3        -0.682695   -0.572152   -0.494856    -0.29308  ...             0   \n",
       "4         0.753100    1.387248    0.468851    -0.29308  ...             0   \n",
       "...            ...         ...         ...         ...  ...           ...   \n",
       "1454     -0.682695   -0.572152   -0.969026    -0.29308  ...             0   \n",
       "1455     -0.682695   -0.572152   -0.415828    -0.29308  ...             0   \n",
       "1456      0.561660   -0.572152    1.717937    -0.29308  ...             0   \n",
       "1457      0.370221   -0.572152   -0.229233    -0.29308  ...             0   \n",
       "1458      0.465941   -0.045913    0.694959    -0.29308  ...             0   \n",
       "\n",
       "      SaleType_WD  SaleType_nan  SaleCondition_Abnorml  SaleCondition_AdjLand  \\\n",
       "0               1             0                      0                      0   \n",
       "1               1             0                      0                      0   \n",
       "2               1             0                      0                      0   \n",
       "3               1             0                      1                      0   \n",
       "4               1             0                      0                      0   \n",
       "...           ...           ...                    ...                    ...   \n",
       "1454            1             0                      0                      0   \n",
       "1455            1             0                      1                      0   \n",
       "1456            1             0                      1                      0   \n",
       "1457            1             0                      0                      0   \n",
       "1458            1             0                      0                      0   \n",
       "\n",
       "      SaleCondition_Alloca  SaleCondition_Family  SaleCondition_Normal  \\\n",
       "0                        0                     0                     1   \n",
       "1                        0                     0                     1   \n",
       "2                        0                     0                     1   \n",
       "3                        0                     0                     0   \n",
       "4                        0                     0                     1   \n",
       "...                    ...                   ...                   ...   \n",
       "1454                     0                     0                     1   \n",
       "1455                     0                     0                     0   \n",
       "1456                     0                     0                     0   \n",
       "1457                     0                     0                     1   \n",
       "1458                     0                     0                     1   \n",
       "\n",
       "      SaleCondition_Partial  SaleCondition_nan  \n",
       "0                         0                  0  \n",
       "1                         0                  0  \n",
       "2                         0                  0  \n",
       "3                         0                  0  \n",
       "4                         0                  0  \n",
       "...                     ...                ...  \n",
       "1454                      0                  0  \n",
       "1455                      0                  0  \n",
       "1456                      0                  0  \n",
       "1457                      0                  0  \n",
       "1458                      0                  0  \n",
       "\n",
       "[2919 rows x 353 columns]"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#将离散值转换成指示特征\n",
    "#假设特征MSZoning中有两个离散值RL和RM，将特征变成两个特征MSZoning_RL和MSZoning_RM\n",
    "# dummy_na=True将缺失值也当作合法的特征值并为其创建指示特征\n",
    "all_features = pd.get_dummies(all_features, dummy_na=True)\n",
    "# print(all_features)\n",
    "# print('-'*20)\n",
    "all_features=all_features*1\n",
    "all_features.shape # (2919, 354)\n",
    "all_features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "113a35b6-7ee2-445c-a0e7-dd0da0a858e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "#将数据转换成NumPy格式的数据，并转成 NDArray ⽅便后⾯的训练\n",
    "n_train = train_data.shape[0]\n",
    "train_features = torch.tensor(all_features[:n_train].values, dtype=torch.float)\n",
    "test_features = torch.tensor(all_features[n_train:].values, dtype=torch.float)\n",
    "train_labels = torch.tensor(train_data.SalePrice.values, dtype=torch.float).view(-1, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "72ed6452-c0e7-41f5-8d63-bf54fe890675",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<bound method Module.parameters of Linear(in_features=5, out_features=1, bias=True)>\n",
      "Parameter containing:\n",
      "tensor([[-0.1251,  0.0237, -0.3072, -0.1699,  0.3486]], device='cuda:0',\n",
      "       requires_grad=True)\n",
      "Parameter containing:\n",
      "tensor([-0.1086], device='cuda:0', requires_grad=True)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Linear(in_features=5, out_features=1, bias=True)"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#基本线性回归模型、平方损失函数\n",
    "loss = torch.nn.MSELoss()\n",
    "def get_net(feature_num):\n",
    "    net = nn.Linear(feature_num, 1)\n",
    "    print(net.parameters)\n",
    "    for param in net.parameters():\n",
    "        print(param)\n",
    "        nn.init.normal_(param, mean=0, std=0.01)\n",
    "    return net\n",
    "\n",
    "get_net(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "879da6ac-6231-4ff7-b5ef-1da872865028",
   "metadata": {},
   "outputs": [],
   "source": [
    "#对数均方根误差\n",
    "def log_rmse(net, features, labels):\n",
    "    with torch.no_grad():\n",
    "        # 将⼩于1的值设成1，使得取对数时数值更稳定\n",
    "        clipped_preds = torch.max(net(features), torch.tensor(1.0))\n",
    "        rmse = torch.sqrt(2 * loss(clipped_preds.log(), labels.log()).mean())\n",
    "    return rmse.item()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "bbe3ce8f-5214-4aed-9f36-9be6290aafcc",
   "metadata": {},
   "outputs": [],
   "source": [
    "#使⽤了Adam优化算法\n",
    "def train(net, train_features, train_labels, test_features, test_labels,num_epochs, learning_rate, weight_decay, batch_size):\n",
    "    train_ls, test_ls = [], []\n",
    "    dataset = torch.utils.data.TensorDataset(train_features, train_labels)\n",
    "    train_iter = torch.utils.data.DataLoader(dataset, batch_size, shuffle=True)\n",
    "    # 这⾥使⽤了Adam优化算法\n",
    "    optimizer = torch.optim.Adam(params=net.parameters(), \n",
    "    lr=learning_rate, weight_decay=weight_decay) \n",
    "    net = net.float()\n",
    "    for epoch in range(num_epochs):\n",
    "        for X, y in train_iter:\n",
    "            l = loss(net(X.float()), y.float())\n",
    "            optimizer.zero_grad()\n",
    "            l.backward()\n",
    "            optimizer.step()\n",
    "        train_ls.append(log_rmse(net, train_features, train_labels))\n",
    "        if test_labels is not None:\n",
    "            test_ls.append(log_rmse(net, test_features, test_labels))\n",
    "    return train_ls, test_ls"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "148744e2-06f0-451d-8332-94cc8e1bfa5d",
   "metadata": {},
   "outputs": [],
   "source": [
    "#K折交叉验证\n",
    "def get_k_fold_data(k, i, X, y):\n",
    "    # 返回第i折交叉验证时所需要的训练和验证数据\n",
    "    assert k > 1\n",
    "    fold_size = X.shape[0] // k\n",
    "    X_train, y_train = None, None\n",
    "    for j in range(k):\n",
    "        idx = slice(j * fold_size, (j + 1) * fold_size)\n",
    "        X_part, y_part = X[idx, :], y[idx]\n",
    "        if j == i:\n",
    "            X_valid, y_valid = X_part, y_part\n",
    "        elif X_train is None:\n",
    "            X_train, y_train = X_part, y_part\n",
    "        else:\n",
    "            X_train = torch.cat((X_train, X_part), dim=0)\n",
    "            y_train = torch.cat((y_train, y_part), dim=0)\n",
    "    return X_train, y_train, X_valid, y_valid"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "fc05cf2d-444b-4d3d-b276-0a12deec5b64",
   "metadata": {},
   "outputs": [],
   "source": [
    "#在K折交叉验证中我们训练K次并返回训练和验证的平均误差。\n",
    "def k_fold(k, X_train, y_train, num_epochs,learning_rate, weight_decay, batch_size):\n",
    "    train_l_sum, valid_l_sum = 0, 0\n",
    "    for i in range(k):\n",
    "        data = get_k_fold_data(k, i, X_train, y_train)\n",
    "        net = get_net(X_train.shape[1])\n",
    "        train_ls, valid_ls = train(net, *data, num_epochs, learning_rate,weight_decay, batch_size)\n",
    "        train_l_sum += train_ls[-1]\n",
    "        valid_l_sum += valid_ls[-1]\n",
    "        if i == 0:\n",
    "            d2l.semilogy(range(1, num_epochs + 1), train_ls, 'epochs', 'rmse',range(1, num_epochs + 1), valid_ls,['train', 'valid'],plot=True)\n",
    "            print('fold %d, train rmse %f, valid rmse %f' % (i, train_ls[-1], valid_ls[-1]))\n",
    "    return train_l_sum / k, valid_l_sum / k"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "252a64ec-7633-4d93-862c-369a5db40f8b",
   "metadata": {},
   "outputs": [
    {
     "ename": "RuntimeError",
     "evalue": "Expected a 'cuda' device type for generator but found 'cpu'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mRuntimeError\u001b[0m                              Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[39], line 3\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m#模型选择\u001b[39;00m\n\u001b[0;32m      2\u001b[0m k, num_epochs, lr, weight_decay, batch_size \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m5\u001b[39m, \u001b[38;5;241m100\u001b[39m, \u001b[38;5;241m5\u001b[39m, \u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m64\u001b[39m\n\u001b[1;32m----> 3\u001b[0m train_l, valid_l \u001b[38;5;241m=\u001b[39m \u001b[43mk_fold\u001b[49m\u001b[43m(\u001b[49m\u001b[43mk\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtrain_features\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtrain_labels\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnum_epochs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlr\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mweight_decay\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbatch_size\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m      4\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m%d\u001b[39;00m\u001b[38;5;124m-fold validation: avg train rmse \u001b[39m\u001b[38;5;132;01m%f\u001b[39;00m\u001b[38;5;124m, avg valid rmse \u001b[39m\u001b[38;5;132;01m%f\u001b[39;00m\u001b[38;5;124m'\u001b[39m \u001b[38;5;241m%\u001b[39m (k, train_l, valid_l))\n",
      "Cell \u001b[1;32mIn[38], line 7\u001b[0m, in \u001b[0;36mk_fold\u001b[1;34m(k, X_train, y_train, num_epochs, learning_rate, weight_decay, batch_size)\u001b[0m\n\u001b[0;32m      5\u001b[0m data \u001b[38;5;241m=\u001b[39m get_k_fold_data(k, i, X_train, y_train)\n\u001b[0;32m      6\u001b[0m net \u001b[38;5;241m=\u001b[39m get_net(X_train\u001b[38;5;241m.\u001b[39mshape[\u001b[38;5;241m1\u001b[39m])\n\u001b[1;32m----> 7\u001b[0m train_ls, valid_ls \u001b[38;5;241m=\u001b[39m \u001b[43mtrain\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnet\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnum_epochs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlearning_rate\u001b[49m\u001b[43m,\u001b[49m\u001b[43mweight_decay\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbatch_size\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m      8\u001b[0m train_l_sum \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m train_ls[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m]\n\u001b[0;32m      9\u001b[0m valid_l_sum \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m valid_ls[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m]\n",
      "Cell \u001b[1;32mIn[35], line 11\u001b[0m, in \u001b[0;36mtrain\u001b[1;34m(net, train_features, train_labels, test_features, test_labels, num_epochs, learning_rate, weight_decay, batch_size)\u001b[0m\n\u001b[0;32m      9\u001b[0m net \u001b[38;5;241m=\u001b[39m net\u001b[38;5;241m.\u001b[39mfloat()\n\u001b[0;32m     10\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m epoch \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(num_epochs):\n\u001b[1;32m---> 11\u001b[0m     \u001b[38;5;28;01mfor\u001b[39;00m X, y \u001b[38;5;129;01min\u001b[39;00m train_iter:\n\u001b[0;32m     12\u001b[0m         l \u001b[38;5;241m=\u001b[39m loss(net(X\u001b[38;5;241m.\u001b[39mfloat()), y\u001b[38;5;241m.\u001b[39mfloat())\n\u001b[0;32m     13\u001b[0m         optimizer\u001b[38;5;241m.\u001b[39mzero_grad()\n",
      "File \u001b[1;32m~\\.conda\\envs\\deep_learning\\lib\\site-packages\\torch\\utils\\data\\dataloader.py:701\u001b[0m, in \u001b[0;36m_BaseDataLoaderIter.__next__\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    698\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sampler_iter \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m    699\u001b[0m     \u001b[38;5;66;03m# TODO(https://github.com/pytorch/pytorch/issues/76750)\u001b[39;00m\n\u001b[0;32m    700\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_reset()  \u001b[38;5;66;03m# type: ignore[call-arg]\u001b[39;00m\n\u001b[1;32m--> 701\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_next_data\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    702\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_num_yielded \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[0;32m    703\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[0;32m    704\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_dataset_kind \u001b[38;5;241m==\u001b[39m _DatasetKind\u001b[38;5;241m.\u001b[39mIterable\n\u001b[0;32m    705\u001b[0m     \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_IterableDataset_len_called \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m    706\u001b[0m     \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_num_yielded \u001b[38;5;241m>\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_IterableDataset_len_called\n\u001b[0;32m    707\u001b[0m ):\n",
      "File \u001b[1;32m~\\.conda\\envs\\deep_learning\\lib\\site-packages\\torch\\utils\\data\\dataloader.py:756\u001b[0m, in \u001b[0;36m_SingleProcessDataLoaderIter._next_data\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    755\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_next_data\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m--> 756\u001b[0m     index \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_next_index\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m  \u001b[38;5;66;03m# may raise StopIteration\u001b[39;00m\n\u001b[0;32m    757\u001b[0m     data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_dataset_fetcher\u001b[38;5;241m.\u001b[39mfetch(index)  \u001b[38;5;66;03m# may raise StopIteration\u001b[39;00m\n\u001b[0;32m    758\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_pin_memory:\n",
      "File \u001b[1;32m~\\.conda\\envs\\deep_learning\\lib\\site-packages\\torch\\utils\\data\\dataloader.py:691\u001b[0m, in \u001b[0;36m_BaseDataLoaderIter._next_index\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    690\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_next_index\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m--> 691\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mnext\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sampler_iter\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[1;32m~\\.conda\\envs\\deep_learning\\lib\\site-packages\\torch\\utils\\data\\sampler.py:347\u001b[0m, in \u001b[0;36mBatchSampler.__iter__\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    345\u001b[0m batch \u001b[38;5;241m=\u001b[39m [\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbatch_size\n\u001b[0;32m    346\u001b[0m idx_in_batch \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[1;32m--> 347\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m idx \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msampler:\n\u001b[0;32m    348\u001b[0m     batch[idx_in_batch] \u001b[38;5;241m=\u001b[39m idx\n\u001b[0;32m    349\u001b[0m     idx_in_batch \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n",
      "File \u001b[1;32m~\\.conda\\envs\\deep_learning\\lib\\site-packages\\torch\\utils\\data\\sampler.py:197\u001b[0m, in \u001b[0;36mRandomSampler.__iter__\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    195\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m    196\u001b[0m     \u001b[38;5;28;01mfor\u001b[39;00m _ \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnum_samples \u001b[38;5;241m/\u001b[39m\u001b[38;5;241m/\u001b[39m n):\n\u001b[1;32m--> 197\u001b[0m         \u001b[38;5;28;01myield from\u001b[39;00m \u001b[43mtorch\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrandperm\u001b[49m\u001b[43m(\u001b[49m\u001b[43mn\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgenerator\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgenerator\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mtolist()\n\u001b[0;32m    198\u001b[0m     \u001b[38;5;28;01myield from\u001b[39;00m torch\u001b[38;5;241m.\u001b[39mrandperm(n, generator\u001b[38;5;241m=\u001b[39mgenerator)\u001b[38;5;241m.\u001b[39mtolist()[\n\u001b[0;32m    199\u001b[0m         : \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnum_samples \u001b[38;5;241m%\u001b[39m n\n\u001b[0;32m    200\u001b[0m     ]\n",
      "File \u001b[1;32m~\\.conda\\envs\\deep_learning\\lib\\site-packages\\torch\\utils\\_device.py:106\u001b[0m, in \u001b[0;36mDeviceContext.__torch_function__\u001b[1;34m(self, func, types, args, kwargs)\u001b[0m\n\u001b[0;32m    104\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m func \u001b[38;5;129;01min\u001b[39;00m _device_constructors() \u001b[38;5;129;01mand\u001b[39;00m kwargs\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mdevice\u001b[39m\u001b[38;5;124m'\u001b[39m) \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m    105\u001b[0m     kwargs[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mdevice\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdevice\n\u001b[1;32m--> 106\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "\u001b[1;31mRuntimeError\u001b[0m: Expected a 'cuda' device type for generator but found 'cpu'"
     ]
    }
   ],
   "source": [
    "#模型选择\n",
    "k, num_epochs, lr, weight_decay, batch_size = 5, 100, 5, 0, 64\n",
    "train_l, valid_l = k_fold(k, train_features, train_labels, num_epochs, lr, weight_decay, batch_size)\n",
    "print('%d-fold validation: avg train rmse %f, avg valid rmse %f' % (k, train_l, valid_l))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8d504330-29c4-4256-acd0-1e0d3a967b7d",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:pytorch]",
   "language": "python",
   "name": "deep_learning"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
